package persistent

import (
	"time"

	"gorm.io/gorm"
)

// TimeoutAlertRecord 超时提醒记录持久化模型
// 对应数据库表timeout_alert_record
type TimeoutAlertRecord struct {
	// ID 记录唯一标识
	ID int64 `gorm:"primaryKey;autoIncrement;column:id" json:"id"`

	// NodeID 节点ID
	NodeID string `gorm:"column:node_id;type:varchar(255);not null;uniqueIndex:uk_node_workflow" json:"node_id"`

	// WorkflowID 工作流ID
	WorkflowID string `gorm:"column:workflow_id;type:varchar(255);not null;uniqueIndex:uk_node_workflow;index:idx_workflow_id" json:"workflow_id"`

	// AlertSentAt 提醒发送时间
	AlertSentAt time.Time `gorm:"column:alert_sent_at;type:timestamp;not null" json:"alert_sent_at"`

	// CreatedAt 创建时间
	CreatedAt time.Time `gorm:"column:created_at;type:timestamp;default:CURRENT_TIMESTAMP" json:"created_at"`

	// UpdatedAt 更新时间
	UpdatedAt time.Time `gorm:"column:updated_at;type:timestamp;default:CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP" json:"updated_at"`
}

// TableName 指定表名
// 返回数据库表名timeout_alert_record
func (TimeoutAlertRecord) TableName() string {
	return "timeout_alert_record"
}

// TimeoutAlertRecordClient 超时提醒记录数据库客户端
// 提供超时提醒记录的数据库操作接口
type TimeoutAlertRecordClient struct {
	db *gorm.DB
}

// NewTimeoutAlertRecordClient 创建超时提醒记录客户端
// 初始化数据库客户端实例
// 参数:
//   - db: GORM数据库连接
//
// 返回值:
//   - *TimeoutAlertRecordClient: 客户端实例
func NewTimeoutAlertRecordClient(db *gorm.DB) *TimeoutAlertRecordClient {
	return &TimeoutAlertRecordClient{db: db}
}

// CheckAlertRecords 批量检查节点是否已发送提醒
// 查询指定工作流下的节点提醒记录状态
// 参数:
//   - nodeIDs: 节点ID列表
//   - workflowID: 工作流ID
//
// 返回值:
//   - map[string]bool: 节点ID到是否已提醒的映射，true表示已提醒
//   - error: 错误信息
func (c *TimeoutAlertRecordClient) CheckAlertRecords(nodeIDs []string, workflowID string) (map[string]bool, error) {
	// 实现步骤：
	// 1. 查询数据库中已存在的提醒记录
	// 2. 构建节点ID到提醒状态的映射
	// 3. 返回结果映射

	if len(nodeIDs) == 0 {
		return make(map[string]bool), nil
	}

	var records []TimeoutAlertRecord
	err := c.db.Where("node_id IN ? AND workflow_id = ?", nodeIDs, workflowID).Find(&records).Error
	if err != nil {
		return nil, err
	}

	// 构建结果映射
	result := make(map[string]bool)
	for _, nodeID := range nodeIDs {
		result[nodeID] = false // 默认未提醒
	}

	// 标记已提醒的节点
	for _, record := range records {
		result[record.NodeID] = true
	}

	return result, nil
}

// CreateAlertRecord 创建超时提醒记录
// 使用UPSERT方式创建或更新提醒记录，确保幂等性
// 参数:
//   - nodeID: 节点ID
//   - workflowID: 工作流ID
//
// 返回值:
//   - error: 错误信息
func (c *TimeoutAlertRecordClient) CreateAlertRecord(nodeID, workflowID string) error {
	// 实现步骤：
	// 1. 构建提醒记录对象
	// 2. 使用FirstOrCreate实现幂等性插入
	// 3. 处理可能的错误

	now := time.Now()
	record := &TimeoutAlertRecord{
		NodeID:      nodeID,
		WorkflowID:  workflowID,
		AlertSentAt: now,
		CreatedAt:   now,
		UpdatedAt:   now,
	}

	// 使用FirstOrCreate确保幂等性
	// 如果记录已存在则不重复创建
	err := c.db.Where("node_id = ? AND workflow_id = ?", nodeID, workflowID).FirstOrCreate(record).Error
	return err
}

// BatchCreateAlertRecords 批量创建超时提醒记录
// 批量插入多个节点的提醒记录，提高性能
// 参数:
//   - nodeIDs: 节点ID列表
//   - workflowID: 工作流ID
//
// 返回值:
//   - error: 错误信息
func (c *TimeoutAlertRecordClient) BatchCreateAlertRecords(nodeIDs []string, workflowID string) error {
	// 实现步骤：
	// 1. 构建批量插入的记录列表
	// 2. 使用事务确保数据一致性
	// 3. 批量插入记录

	if len(nodeIDs) == 0 {
		return nil
	}

	now := time.Now()
	records := make([]TimeoutAlertRecord, 0, len(nodeIDs))

	for _, nodeID := range nodeIDs {
		records = append(records, TimeoutAlertRecord{
			NodeID:      nodeID,
			WorkflowID:  workflowID,
			AlertSentAt: now,
			CreatedAt:   now,
			UpdatedAt:   now,
		})
	}

	// 使用事务批量插入
	return c.db.Transaction(func(tx *gorm.DB) error {
		for _, record := range records {
			if err := tx.Where("node_id = ? AND workflow_id = ?", record.NodeID, record.WorkflowID).FirstOrCreate(&record).Error; err != nil {
				return err
			}
		}
		return nil
	})
}
